package demo.kk;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 高并发库存超卖问题演示
 */
public class HighConcurrencyProblemDemo {

    // 模拟商品库存
    public static class ProductInventory {
        private int stock; // 库存数量

        public ProductInventory(int stock) {
            this.stock = stock;
        }

        // 错误的购买方法：非线程安全
        public boolean purchaseUnsafe() {
            if (stock > 0) {
                try {
                    // 模拟业务处理耗时（数据库操作、验证等）
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                stock--; // 核心问题：非原子操作
                return true;
            }
            return false;
        }

        public int getStock() {
            return stock;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final int userCount = 10000; // 模拟用户数
        final int initialStock = 1000; // 初始库存
        final ProductInventory inventory = new ProductInventory(initialStock);

        // 使用CountDownLatch模拟高并发同时请求
        CountDownLatch latch = new CountDownLatch(userCount);

        // 成功抢到商品的用户数
        AtomicInteger successCount = new AtomicInteger(0);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < userCount; i++) {
            new Thread(() -> {
                try {
                    // 等待所有线程准备就绪，模拟同时发起请求
                    latch.await();
                    if (inventory.purchaseUnsafe()) {
                        synchronized (HighConcurrencyProblemDemo.class) {
                            successCount.addAndGet(1);
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            latch.countDown(); // 准备完成一个线程
        }

        // 等待所有线程执行完成
        Thread.sleep(3000);

        long endTime = System.currentTimeMillis();

        System.out.println("========= 错误结果 =========");
        System.out.println("初始库存: " + initialStock);
        System.out.println("参与抢购用户数: " + userCount);
        System.out.println("实际售出商品: " + successCount);
        System.out.println("剩余库存: " + inventory.getStock());
        System.out.println("总耗时: " + (endTime - startTime) + "ms");

        // 理论上应该满足：initialStock = successCount + inventory.getStock()
        // 但由于线程不安全，这个等式通常不成立
        System.out.println("数据一致性检查: " +
                (initialStock == (successCount.get() + inventory.getStock()) ? "✓ 通过" : "✗ 失败（出现超卖）"));
    }
}